/*******************************************************************************
 * Copyright 2009 Dop Sun
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
/**
 * Place holder for copyright, needs to be replaced before release.
 */
package com.softao.ming.gde.internal.ui.launcher;

import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtension;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jdt.launching.IJavaLaunchConfigurationConstants;
import org.eclipse.pde.core.plugin.TargetPlatform;
import org.eclipse.pde.ui.launcher.IPDELauncherConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;

import com.softao.ming.gde.internal.core.pde.PdeCoreUtil;

/**
 * 
 */
public class ProgramBlock extends AbstractGroupBlock {
	class Listener extends SelectionAdapter {
		public void widgetSelected(SelectionEvent e) {
			Object source = e.getSource();
			if (source == fProductButton) {
				boolean enabled = fProductButton.getSelection();
				fProductCombo.setEnabled(enabled);
				fApplicationCombo.setEnabled(!enabled);
			}
			getTab().updateLaunchConfigurationDialog();
		}
	}
	
	private Combo fApplicationCombo;
	private Button fProductButton;
	private Combo fProductCombo;
	private Button fApplicationButton;
	private Listener fListener = new Listener();

	/**
	 * @param tab
	 */
	public ProgramBlock(GwtLaunchTab tab) {
		super(tab);
	}

	@Override
	protected void createContent(Composite parent) {
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		parent.setLayout(layout);
		parent.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		createProductSection(parent);
		createApplicationSection(parent);
	}

	@Override
	protected String getText() {
		return "Program to Run";
	}

	private void createProductSection(Composite parent) {
		fProductButton = new Button(parent, SWT.RADIO);
		fProductButton.setText("Run a &product:");
		fProductButton.addSelectionListener(fListener);

		fProductCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
		fProductCombo.setItems(getProductNames());
		fProductCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fProductCombo.addSelectionListener(fListener);
	}

	private void createApplicationSection(Composite parent) {
		fApplicationButton = new Button(parent, SWT.RADIO);
		fApplicationButton.setText("Run an &application:");

		fApplicationCombo = new Combo(parent, SWT.READ_ONLY | SWT.DROP_DOWN);
		fApplicationCombo.setItems(getApplicationNames());
		fApplicationCombo.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		fApplicationCombo.addSelectionListener(fListener);
	}

	public void initializeFrom(ILaunchConfiguration config) throws CoreException {
		initializeProductSection(config);
		initializeApplicationSection(config);

		boolean useProduct = config.getAttribute(IPDELauncherConstants.USE_PRODUCT, false) && fProductCombo.getItemCount() > 0;
		fApplicationButton.setSelection(!useProduct);
		fApplicationCombo.setEnabled(!useProduct);
		fProductButton.setSelection(useProduct);
		fProductButton.setEnabled(fProductCombo.getItemCount() > 0);
		fProductCombo.setEnabled(useProduct);
	}

	private void initializeProductSection(ILaunchConfiguration config) throws CoreException {
		if (fProductCombo.getItemCount() > 0) {
			String productName = config.getAttribute(IPDELauncherConstants.PRODUCT, (String) null);
			int index = productName == null ? -1 : fProductCombo.indexOf(productName);
			if (index == -1)
				index = 0;
			fProductCombo.setText(fProductCombo.getItem(index));
		}
	}

	private void initializeApplicationSection(ILaunchConfiguration config) throws CoreException {

		String attribute = getApplicationAttribute();

		// first see if the application name has been set on the launch config
		String application = config.getAttribute(attribute, (String) null);
		if (application == null || fApplicationCombo.indexOf(application) == -1) {
			application = null;

			// check if the user has entered the -application arg in the program arg field
			StringTokenizer tokenizer = new StringTokenizer(config.getAttribute(IJavaLaunchConfigurationConstants.ATTR_PROGRAM_ARGUMENTS, "")); //$NON-NLS-1$
			while (tokenizer.hasMoreTokens()) {
				String token = tokenizer.nextToken();
				if (token.equals("-application") && tokenizer.hasMoreTokens()) { //$NON-NLS-1$
					application = tokenizer.nextToken();
					break;
				}
			}

			int index = -1;
			if (application != null)
				index = fApplicationCombo.indexOf(application);

			// use default application as specified in the install.ini of the target platform
			if (index == -1)
				index = fApplicationCombo.indexOf(TargetPlatform.getDefaultApplication());

			if (index != -1) {
				fApplicationCombo.setText(fApplicationCombo.getItem(index));
			} else if (fApplicationCombo.getItemCount() > 0) {
				fApplicationCombo.setText(fApplicationCombo.getItem(0));
			}
		} else {
			fApplicationCombo.setText(application);
		}
	}

	public void performApply(ILaunchConfigurationWorkingCopy config) {
		saveApplicationSection(config);
		saveProductSection(config);
	}

	private void saveProductSection(ILaunchConfigurationWorkingCopy config) {
		config.setAttribute(IPDELauncherConstants.USE_PRODUCT, fProductButton.getSelection());
		config.setAttribute(IPDELauncherConstants.PRODUCT, fProductCombo.getText());
	}

	private void saveApplicationSection(ILaunchConfigurationWorkingCopy config) {
		String text = fApplicationCombo.getText();
		String attribute = getApplicationAttribute();
		if (text.length() == 0 || text.equals(TargetPlatform.getDefaultApplication()))
			config.setAttribute(attribute, (String) null);
		else
			config.setAttribute(attribute, text);
	}

	public void setDefaults(ILaunchConfigurationWorkingCopy config) {
		String product = TargetPlatform.getDefaultProduct();
		if (product != null) {
			config.setAttribute(IPDELauncherConstants.USE_PRODUCT, true);
			config.setAttribute(IPDELauncherConstants.PRODUCT, product);
		}
	}

	private String getApplicationAttribute() {
		return IPDELauncherConstants.APPLICATION;
	}

	private static TreeSet<String> getProductNameSet() {
		TreeSet<String> result = new TreeSet<String>();
		IExtension[] extensions = PdeCoreUtil.findExtensions("com.softao.ming.gwt.core.runtime.products", true); //$NON-NLS-1$
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i].getConfigurationElements();
			for (IConfigurationElement element : elements) {
				if ("product".equals(element.getName())) {
					String id = element.getAttribute("id");
					if (id != null && id.trim().length() > 0) {
						result.add(id);
					}
				}
			}
		}
		return result;
	}

	private static String[] getProductNames() {
		TreeSet<String> result = getProductNameSet();
		return result.toArray(new String[result.size()]);
	}

	private static Set<String> getApplicationNameSet() {
		TreeSet<String> result = new TreeSet<String>();
		IExtension[] extensions = PdeCoreUtil.findExtensions("com.softao.ming.gwt.core.runtime.applications", true); //$NON-NLS-1$
		for (int i = 0; i < extensions.length; i++) {
			IConfigurationElement[] elements = extensions[i].getConfigurationElements();
			for (IConfigurationElement element : elements) {
				if ("application".equals(element.getName())) {
					String id = element.getAttribute("id");
					if (id != null && id.trim().length() > 0) {
						result.add(id);
					}
				}
			}
		}
		return result;
	}

	private static String[] getApplicationNames() {
		Set<String> result = getApplicationNameSet();
		return result.toArray(new String[result.size()]);
	}
}
